package tailflog

import (
	"context"
	"errors"
	"fmt"
	//"github.com/gomodule/redigo/redis"
	"github.com/hpcloud/tail"
	"log"
	"os"
	"time"
)

const (
	AccessLog = "/data/logs/access.log"
	RedisAddr = "127.0.0.1:6379"
	RedisDB   = 9
	RedisPass = "pass@wd"
)

type slog struct {
	Name string `json:"name"`
	Path string `json:"path"`
}

type msg struct {
	LogName string `json:"logName"`
	Data    string `json:"data"`
}

var slogs = []slog{}

func printInfo(msg string) {
	log.Printf("[seelog] Info: %s\n", msg)
}

func printError(err error) {
	log.Printf("[seelog] Error: %+v\n", err)
}

// See 添加监听的文件
func See(name, path string) {
	if name == "" || path == "" {
		printError(errors.New("log名称或者路径不可为空"))
		return
	}

	for _, sl := range slogs {
		if sl.Name == name {
			printError(errors.New(fmt.Sprintf("log名称 %s 已存在,不可重复", name)))
			return
		}
	}
	slogs = append(slogs, slog{name, path})
}

// Serve 开始监控
func Serve(port int, seelog string) {

	if port < 0 || port > 65535 {
		printError(errors.New("端口号不符合规范，port(0,65535)"))
		return
	}

	if len(slogs) < 1 {
		printError(errors.New("至少监听一个日志文件,请使用 seelog.See(name,path string)"))
		return
	}
	// 开启socket管理器
	go Manager.start()

	// 监控文件
	go Monitor()

	// 开启httpServer
	go server(port, seelog)
}

// Monitor 监控日志文件
func Monitor() {
	for _, sl := range slogs {
		go func(sl slog) {
			defer func() {
				if err := recover(); err != nil {
					printError(errors.New("monitor() panic"))
				}
			}()

			var filesize int64 = 0
			// 等待文件
			fileInfo, err := os.Stat(sl.Path)
			if err != nil {
				printInfo(fmt.Sprintf("等待文件 %s 生成", sl.Path))
				ctx, _ := context.WithTimeout(context.Background(), time.Minute*5)
				fileInfo, err = BlockUntilExists(sl.Path, ctx)
				if err != nil {
					printError(err)
					return
				}
			}

			if fileInfo.Size() >= 10000 {
				filesize = 10000
			} else {
				filesize = fileInfo.Size()
			}

			t, _ := tail.TailFile(sl.Path, tail.Config{
				Follow:    true,
				MustExist: false,
				Poll:      true,
				Location:  &tail.SeekInfo{Offset: filesize, Whence: 0},
			})

			for line := range t.Lines {
				Manager.broadcast <- msg{sl.Name, line.Text}
			}
		}(sl)
	}
}

func BlockUntilExists(fileName string, ctx context.Context) (os.FileInfo, error) {
	for {
		f, err := os.Stat(fileName)
		if err == nil {
			return f, nil
		}

		select {
		case <-time.After(time.Millisecond * 200):
			continue
		case <-ctx.Done():
			return nil, errors.New(fmt.Sprintf("等待 %s 超时", fileName))
		}
	}
}

//
//func getFilePath(key string) (filepath string) {
//	pool := redis.Pool{
//		MaxActive: 10,
//		MaxIdle:   5,
//		Dial: func() (conn redis.Conn, e error) {
//			c, err := redis.Dial(
//				"tcp",
//				RedisAddr,
//				redis.DialPassword(RedisPass),
//				redis.DialDatabase(RedisDB))
//			if err != nil {
//				printError(err)
//				return nil, err
//			}
//			return c, nil
//		},
//	}
//	c := pool.Get()
//	defer c.Close()
//
//	v, err := redis.String(c.Do("GET", key))
//	if err != nil {
//		printError(err)
//	}
//	return
//}
